package com.lagou;

import com.lagou.bean.ConsumerComponent;
import com.lagou.bean.MethodCallTime;
import com.lagou.filter.TPMonitorFilter;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

import java.io.IOException;
import java.nio.channels.NonWritableChannelException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ServiceConsumerMain {

    public static void main(String[] args) throws IOException, InterruptedException {

        AnnotationConfigApplicationContext context = new
                AnnotationConfigApplicationContext(ConsumerConfiguration.class);
        context.start();
        // 获取消费者组件
        ConsumerComponent service = context.getBean(ConsumerComponent.class);

        // 创建固定线程池
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        // 调用方法A
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    service.sayHelloA();
                }
            }
        });

        // 调用方法B
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    service.sayHelloB();
                }
            }
        });

        // 调用方法C
        executorService.submit(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    service.sayHelloC();
                }
            }
        });

        // 每隔5s打印一次最近1分钟内每个方法的TP90、TP99的耗时情况
        while (true) {
            Thread.sleep(5000);
            // 方法A统计打印
            statisticsMethodCall(TPMonitorFilter.queueA, "MethodA");
            // 方法B统计打印
            statisticsMethodCall(TPMonitorFilter.queueB, "MethodB");
            // 方法C统计打印
            statisticsMethodCall(TPMonitorFilter.queueC, "MethodC");
            System.out.println("====================================================================");
        }
    }

    @Configuration
    @PropertySource("classpath:dubbo-consumer.properties")
    @ComponentScan(value = {"com.lagou.bean"})
    @EnableDubbo
    static class ConsumerConfiguration {

    }

    // 方法调用统计
    private static void statisticsMethodCall(LinkedList<MethodCallTime> queue, String methodName) {
        // 耗时记录
        List<Long> resTimes = new ArrayList<>();
        // 当前时间
        Long curTime = System.currentTimeMillis();
        // 60秒前的时间点
        Long pre60Time = curTime - (60 * 1000);

        // 取一分钟内的数据，按照响应时间进行排序
        Iterator<MethodCallTime> iterator = queue.iterator();
        while (iterator.hasNext()) {
            MethodCallTime callTime = iterator.next();
            // 请求完成时间
            long endTime = callTime.getEndTime();
            if(endTime < pre60Time){ // 元素超过一分钟之前
                // 可以将一分钟之前的数据删除
                iterator.remove();
            }else if(pre60Time <=endTime && endTime <= curTime){ // 一分钟之内的
                // 保存
                resTimes.add(callTime.getCallTime());
            }
        }

        // 耗时从小到大排序
        Collections.sort(resTimes);
        int TP90 = (int)(resTimes.size() * 0.90);
        int TP99 = (int)(resTimes.size() * 0.99);
        System.out.println(String.format("方法：%s ====> 统计次数；%d， T90性能：%d，T99性能：%d.",
                methodName, resTimes.size(), resTimes.get(TP90), resTimes.get(TP99)));
    }
}
